/**
 *	\file
 *	\brief represents the schema of the type owned by a particular identifier
 *
 * 	\date Aug 30, 2013
 * 	\author koldar
 */

#ifndef SCHEMA_H_
#define SCHEMA_H_

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include "schemaClassType.h"

/**value to be set to className Schema field if the schema represents no class
 *
 */
#define SCHEMA_NOCLASS "$"
/**value to be set to arrayLength Schema field if the schema represents no array
 *
 */
#define SCHEMA_NOARRAY -1

/**represents the type of a variable (or constant)
 *
 */
typedef struct Schema {
	SchemaClassType class; //!< indicates what type this schema is representing. See SchemaClassType for the possible values
	char* className; //!< represents the class of this variable. If this schema isn't representing any classes, this value must be SCHEMA_NOCLASS
	int arraylength; //!< represents the length of this array. If this schema isn't representing any array, this value must be SCHEMA_NOARRAY
	struct Schema* arrayType; //!< represents the schema of every cell in the array. If this schema isn't representing any array, this value must be NULL
} Schema;

/** pointer to a Schema structure
 *
 */
typedef Schema* Pschema;

/**initialize a new schema type for a simple field
 *
 * \pre
 *  \li _class must be on of these vlaues: INT, FLOAT, CHAR, STRING, BOOL;
 * \post
 *  \li a new Schema structure is present in the memory. Free it with freeSchema() or freeSchemaFull()
 *
 * @param _class the class of the variable
 * @return a pointer to the newly created structure
 */
Pschema initSchemaSimple(SchemaClassType _class);

/**initialize a new schema type for a class field
 *
 * \pre
 *  \li _className must be not NULL
 * \post
 *  \li a new Schema structure is present in the memory. Free it with freeSchema() or freeSchemaFull()
 *
 * @param _className the name of the class
 * @return a pointer to the newly created structure
 */
Pschema initSchemaClass(char* _className);

/**initialize a new schema type for an array type
 *
 * \pre
 *  \li _arraylength must be greater than 0
 *  \li _arrayType must not be NULL
 * \post
 *  \li a new Schema structure is present in the memory. Free it with freeSchema() or freeSchemaFull()
 *
 * @param _arraylength the length of the array
 * @param _arrayType the type of every cell present in this array
 * @return a pointer to the newly created structure
 */
Pschema initSchemaArray(int _arraylength, Pschema _arrayType);

/**delete from the memory the pobj. If the schema is representing an array the Schema pointed by it will <b>not</b> be erase.
 * To that purpose, use freeSchemaFull().
 * For clearify the function the red nodes will be freed while the black ones won't.
 *
 * \dot
 *  digraph free {
 *  	arrayType1 [label="array type\narraylength=10" color="red"];
 *  	arrayType2 [label="array type\narraylength=5"];
 *  	int;
 *
 *  	arrayType1 -> arrayType2 -> int;
 *  }
 * \enddot
 *
 * \pre
 *  \li pobj is not NULL
 *
 * @param pobj the Schema pointed by pobj is correctly deallocated
 */
void freeSchema(Pschema pobj);

/**delete from the memory the pobj. If the schema is representing an array the Schema pointed by it will be erase recursively.
 * For clearify the function the red nodes will be freed while the black ones won't.
 *
 * \dot
 *  digraph free {
 *  	arrayType1 [label="array type\narraylength=10" color="red"];
 *  	arrayType2 [label="array type\narraylength=5" color="red"];
 *  	int [color="red"];
 *
 *  	arrayType1 -> arrayType2 -> int;
 *  }
 * \enddot
 *
 * \pre
 *  \li pobj is not NULL
 *
 * @param pobj the Schema pointed by pobj is correctly deallocated
 */
void freeSchemaFull(Pschema pobj);

/**print a <b>full</b> string representation of this schema object.
 * if pobj is NULL "void" is printed.
 *
 * \pre
 *  \li f open in write mode
 * \post
 *  \li the string representation does have <b>no</b> carriage returns;
 *  \li "VOID" is printed if the schema is NULL;
 *  \li "array [0..x] of y" is printed if the schema is an array;
 *  \li "class x" is printed if the schema is a class;
 *  \li "x" is printed if the schema is a simple type;
 *
 * @param f the file to write on
 * @param pobj the object to be written
 */
void printSchema(FILE* f,Pschema pobj);

/**generates a jpg image of the current full schema.
 *
 * \pre
 *  \li filename is a correct file system file name
 *  \li filename does not contain the any extension
 *  \li pobj not NULL
 *  \li pobj represents a correct Schema
 * \post
 *  \li a jpg image called filename.jpg is stored in the grp directory of this project
 *
 * @param filename the name of the output file
 * @param pobj the Schema to be represented
 */
void dotSchemaFull(const char* filename,Pschema pobj);

#endif /* SCHEMA_H_ */
